var typeAhead = 3;
var typedAlready = 0;
var SwappableTags = Class.create({
    initialize: function(element, options) {
      this.element = $(element);
      
      this.options = Object.extend({
      	stockTagsList:   this.element.readAttribute("id")+"List",
      	classNameUsed:   "used"
      }, options || {});
      
      this.listElements = $(this.options.stockTagsList).select("*");

      
      this.stockTags   = this.parseStockTags();

      this.element.observe("focus", this.onFocus);
      this.element.observe("blur",  this.onBlur);
      this.element.observe("keyup", this.onKeyup.bind(this));

	  new Field.Observer(this.element, 0.1, this.updateRecordTagsClassName.bind(this));

      this.prepare();
    },
    
    prepare: function() {
			this.listElements.each(function(element) {
				element.update(new Element("a", { href: "#" }).update(element.innerHTML.strip()));
				element.down("a").observe("click", this.onClickStockTag.bind(this));
			}, this);
    	this.updateRecordTagsClassName();
    },
    
    onFocus: function(e) {
    	typedAlready = 0;
		
    	if (!e.element().present()) { return; }
			while (/\W/.test($F(e.element()).charAt($F(e.element()).length-1))) {
				e.element().setValue($F(e.element()).substring(0, ($F(e.element()).length-1)));
			}
			e.element().setValue($F(e.element())+", ");
			if (e.element().createTextRange) { 
				var range = e.element().createTextRange(); 
				range.moveStart("character", $F(e.element()).length); 
				range.moveEnd("character", 0);      
				range.select(e.element());
			}
    },
    
    onBlur: function(e) {
    	typedAlready = 0;
		    	
		while (/\W/.test($F(e.element()).charAt($F(e.element()).length-1))) {
			e.element().setValue($F(e.element()).substring(0, ($F(e.element()).length-1)));
		}
    },
    onKeyupNew: function(e) {
    	var oldValue, newValue;
      	var recordTags = this.getRecordTags();
      	var lastRecordTag = recordTags.last();
			if ([Event.KEY_BACKSPACE, 
           Event.KEY_TAB, 
           Event.KEY_RETURN, 
           Event.KEY_ESC, 
           Event.KEY_LEFT, 
           Event.KEY_UP, 
           Event.KEY_RIGHT, 
           Event.KEY_DOWN      ].include(e.keyCode) || !lastRecordTag || lastRecordTag.length < 1) { return; }
			
    	this.stockTags.each(function(tag, i) {
    		if (tag.startsWith(lastRecordTag) && !recordTags.include(tag)) {
    			oldValue = $F(e.element());
    			newValue = recordTags.without(lastRecordTag).concat([tag]).join(", ");
    		
    			e.element().setValue(newValue);
    									
				if (e.element().createTextRange) {
					var range = e.element().createTextRange(); 
					range.moveStart("character", oldValue.length); 
					range.moveEnd("character", newValue.length - oldValue.length);      
					range.select(e.element());
				} else if (e.element().setSelectionRange) {
					e.element().setSelectionRange(oldValue.length, newValue.length);
				}
				return;
    		} 
    	}, this);
	},     
    onKeyup: function(e) {
    	if (e.keyCode == 188) {
    		/*
    		 * If keypress == comma, reset typedAlready counter
    		 */
    		typedAlready = 0;
    	} else {
			typedAlready++;
    	}	
		if (typedAlready > typeAhead) {
			this.onKeyupNew(e);
		}		
	}, 
    
    parseStockTags: function() {
    	var stockTags = [];
    	this.listElements.each(function(li) {
    		var tag = li.innerHTML.strip();
    		if (!tag.blank()) { stockTags.push(tag); }
    	}, this);
    	return stockTags;
    },
    
    getRecordTags: function() {
    	return (this.element.present() ? $F(this.element).split(",").invoke("strip") : []);
    },
    
    onClickStockTag: function(e) {
    	e.stop();
    	if ([this.element, this.element.up("form")].pluck("disabled").any()) { return false; }
    	var tag = e.element().innerHTML.strip();
    	
    	var recordTags = this.getRecordTags();

    	if (recordTags.include(tag)) {
    		recordTags = recordTags.without(tag);
    	} else {    		
   			recordTags.push(tag);
    	}
    	this.element.setValue(recordTags.join(", "));
    	this.updateRecordTagsClassName();
    },
    
    updateRecordTagsClassName: function() {
      var recordTags = this.getRecordTags();
    	this.stockTags.each(function(tag, i) {
    		this.listElements[i][recordTags.include(tag) ? "addClassName" : "removeClassName"](this.options.classNameUsed);
    	}, this);
		} 
	});